#ifndef HSL_HEURISTIC_SELECTOR_H
#define HSL_HEURISTIC_SELECTOR_H

#include "Heuristic.h"
#include <algorithm>


/// R1: the resource type present in output of selection. 
/// R2: the resource type used for selecting allocation.
template <class H, class R1, class R2=R1>
class HeuristicSelectorBase {
public:
    /* construction */

    /// :: must define ::
    void registerHeuristic(std::unique_ptr<H> h) {
        heuristics_.push_back(h); 
    }
    
    ~HeuristicSelectorBase() {
        std::for_each(heuristics_.begin(), heuristics_.end(), 
            [this] (typename std::vector<H*>::value_type v) { delete v; }); 
    }
    
    /* other functions */

    /// :: must define ::
    std::unique_ptr<HeuristicResourceAllocations<H, R2>> select(const R1& r);
private:
   std::vector<H*> heuristics_; 
};


/// H: Heuristic
/// R: Resources
template <class H, class R>
class HeuristicResourceAllocations {
    typedef std::map<H*, R*> HeuristicResourceMap;
public:

    /* construction */
    
    void addHeuristicResource(H& h, std::unique_ptr<R> r); 

    ~HeuristicResourceAllocations() {
        std::for_each(heuristicResourceMap_.begin(), heuristicResourceMap_.end(), 
            [this] (typename HeuristicResourceAllocations<H, R>::HeuristicResourceMap::value_type v) { delete v.second; }); 
    }

    /* accessor functions */

    const R& getAllocationForHeuristic(H& h) {
        return heuristicResourceMap_[&h];
    }

    typedef typename HeuristicResourceMap::iterator iterator;
    iterator begin() { return heuristicResourceMap_.begin(); } 
    iterator end()   { return heuristicResourceMap_.end(); } 

private:
    HeuristicResourceMap heuristicResourceMap_;
};

#endif
